﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Xml;
using Common.Utilities;
using Common.Utilities.Dispatcher;

namespace Workflows.Components.Entities.MasterData
{
    /// <summary>
    /// all fields must be derived from the same table or sql
    /// </summary>
    [Serializable]
    public class FieldInteractionInstruction:InstructionBase
    {
        #region props
        private string _ConnStr;
        /// <summary></summary>
        public string ConnStr
        {
            get
            {
                return this._ConnStr;
            }
            set
            {
                this._ConnStr = value;
            }
        }

        private string _SchemaName;
        /// <summary></summary>
        public string SchemaName
        {
            get
            {
                return this._SchemaName;
            }
            set
            {
                this._SchemaName = value;
            }
        }

        private string _TblName;
        /// <summary></summary>
        public string TblName
        {
            get
            {
                return this._TblName;
            }
            set
            {
                this._TblName = value;
            }
        }

        private string _Sql;
        /// <summary></summary>
        public string Sql
        {
            get
            {
                return this._Sql;
            }
            set
            {
                this._Sql = value;
            }
        }

        private string _DeterminantField;
        /// <summary></summary>
        public string DeterminantField
        {
            get
            {
                return this._DeterminantField;
            }
            set
            {
                this._DeterminantField = value;
            }
        }

        private List<string> _DependentFields;
        /// <summary></summary>
        public List<string> DependentFields
        {
            get
            {
                return this._DependentFields;
            }
            set
            {
                this._DependentFields = value;
            }
        }

        private string _OutputFilePath;
        /// <summary></summary>
        public string OutputFilePath
        {
            get
            {
                return this._OutputFilePath;
            }
            set
            {
                this._OutputFilePath = value;
            }
        }
        #endregion

        #region ctor 
        public FieldInteractionInstruction():base(Guid.Empty, Guid.Empty)
        {
            this._ConnStr = string.Empty;
            this._SchemaName = string.Empty;
            this._TblName = string.Empty;
            this._Sql = string.Empty;
            this._DeterminantField = string.Empty;
            this._DependentFields=new List<string>();
            this._OutputFilePath = string.Empty;
        }

        public FieldInteractionInstruction(Guid componentID, Guid jobTicketID,
            string connStr, string schemaName, string tblName, string sql,
            string determinantField, List<string> dependentFields, 
            string outputFilePath) : base(componentID, jobTicketID)
        {
            this._ConnStr = connStr;
            this._SchemaName = schemaName;
            this._TblName = tblName;
            this._Sql = sql;
            this._DeterminantField = determinantField;
            this._DependentFields = dependentFields;
            this._OutputFilePath = outputFilePath;
        }
        #endregion

        #region Overrides of InstructionBase

        /// <summary>
        /// serialize settings to xml
        /// the function below is mainly for storing into database as serialized form instead of string
        /// </summary>
        public override XmlNode Serialize(ref XmlDocument xDoc, ref XmlNode parentNode)
        {
            XmlNode xNode = XmlDataUtil.AddElement(ref xDoc, parentNode, "Instruction");
            XmlDataUtil.UpdateAttribute(ref xDoc, xNode, "Type", this.GetType().FullName);
            XmlDataUtil.UpdateAttribute(ref xDoc, xNode, "ComponentID", this.OwnerComponentID.ToString());
            XmlDataUtil.UpdateAttribute(ref xDoc, xNode, "WorkerID", this.OwnerWorkerInstanceID.ToString());
            XmlDataUtil.UpdateAttribute(ref xDoc, xNode, "SubmitTime", this.SubmitTime.ToString());
            XmlDataUtil.UpdateAttribute(ref xDoc, xNode, "StartTime", this.StartTime.ToString());

            XmlDataUtil.UpdateAttribute(ref xDoc, xNode, "ConnStr", this.ConnStr);
            XmlDataUtil.UpdateAttribute(ref xDoc, xNode, "SchemaName", this.SchemaName);
            XmlDataUtil.UpdateAttribute(ref xDoc, xNode, "TblName", this.TblName);
            XmlDataUtil.UpdateAttribute(ref xDoc, xNode, "Sql", this.Sql);
            XmlDataUtil.UpdateAttribute(ref xDoc, xNode, "DeterminantField", this.DeterminantField);
            XmlDataUtil.UpdateAttribute(ref xDoc, xNode, "OutputFilePath", this.OutputFilePath);
            XmlNode dependentNodes = XmlDataUtil.AddElement(ref xDoc, xNode, "DependentFields");
            if(this.DependentFields !=null && this.DependentFields.Count>0)
            {
                foreach(string dependentField in this.DependentFields)
                {
                    XmlNode dependentNode = XmlDataUtil.AddElement(ref xDoc, dependentNodes, "DependentField");
                    XmlDataUtil.UpdateAttribute(ref xDoc, dependentNode,"FieldName",dependentField);
                }
            }

            return xNode;
        }

        /// <summary>
        /// instantiated from xml
        /// "&lt;Instructions&gt;&lt;Instruction&gt;&lt;/Instruction&gt;&lt;/Instruction&gt;", must
        /// instantiate from first child of root node
        /// </summary>
        public override InstructionBase Instantiate(XmlNode xNode)
        {
            if (xNode.Attributes.GetNamedItem("Type").Value == this.GetType().FullName)
            {
                FieldInteractionInstruction instruction = new FieldInteractionInstruction();
                instruction.OwnerComponentID = new Guid(xNode.Attributes.GetNamedItem("ComponentID").Value);
                instruction.OwnerWorkerInstanceID = new Guid(xNode.Attributes.GetNamedItem("WorkerID").Value);
                instruction.SubmitTime = DateTime.Parse(xNode.Attributes.GetNamedItem("SubmitTime").Value);
                instruction.StartTime = DateTime.Parse(xNode.Attributes.GetNamedItem("StartTime").Value);

                instruction.ConnStr = XmlDataUtil.GetAttributeValue(xNode, "ConnStr", "");
                instruction.SchemaName = XmlDataUtil.GetAttributeValue(xNode, "SchemaName", "");
                instruction.TblName = XmlDataUtil.GetAttributeValue(xNode, "TblName", "");
                instruction.Sql = XmlDataUtil.GetAttributeValue(xNode, "Sql", "");
                instruction.DeterminantField = XmlDataUtil.GetAttributeValue(xNode, "DeterminantField", "");
                instruction.OutputFilePath = XmlDataUtil.GetAttributeValue(xNode, "OutputFilePath", "");
                instruction.DependentFields=new List<string>();
                XmlNodeList depNodes = xNode.SelectNodes("DependentFields/DependentField");
                if (depNodes != null && depNodes.Count > 0)
                {
                    foreach (XmlNode depNode in depNodes)
                    {
                        instruction.DependentFields.Add(XmlDataUtil.GetAttributeValue(depNode, "FieldName", ""));
                    }
                }
                return instruction;
            }
            else
            {
                throw new Exception("Unable to instantiate instruction: invalid type specified in xml node");
            }
        }

        #endregion
    }
}
